﻿//TODO: test, BackgroundByColor

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

using LowLevelGraphics.Histograms;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// background by color modes
    /// </summary>
    public enum BACKGROUNDBYCOLOR_MODE
    {
        AVERAGE_COLOR, //average value of all colors
        DOMINANT_COLOR, //most counts
        MEAN_COLOR,     //mean color
        LUMINANCE_COLOR //luminance color
    }

    /// <summary>
    /// Background by color
    /// </summary>
    public class BackgroundByColor : BaseImageFilter
    {
        protected int m_nR = 10;
        protected int m_nG = 10;
        protected int m_nB = 10;

        protected BACKGROUNDBYCOLOR_MODE M_MODE = BACKGROUNDBYCOLOR_MODE.AVERAGE_COLOR;

        /// <summary>
        /// Default constructor
        /// </summary>
        public BackgroundByColor()
            : this(BACKGROUNDBYCOLOR_MODE.DOMINANT_COLOR, 10, 10, 10)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BackgroundByColor"/> class.
        /// </summary>
        /// <param name="r">The r.</param>
        /// <param name="g">The g.</param>
        /// <param name="b">The b.</param>
        public BackgroundByColor(int r, int g, int b)
            : this(BACKGROUNDBYCOLOR_MODE.DOMINANT_COLOR, r, g, b)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BackgroundByColor"/> class.
        /// </summary>
        /// <param name="_mode">The _mode.</param>
        /// <param name="_r">The _r.</param>
        /// <param name="_g">The _g.</param>
        /// <param name="_b">The _b.</param>
        public BackgroundByColor(BACKGROUNDBYCOLOR_MODE _mode, int _r, int _g, int _b)
        {
            MODE = _mode;
            m_nR = 10;
            m_nG = 10;
            m_nB = 10;
        }

        /// <summary>
        /// used by clone to create a deep copy
        /// </summary>
        /// <param name="_backgroundByColor"></param>
        internal BackgroundByColor(BackgroundByColor _backgroundByColor)
        {
            this.M_MODE = _backgroundByColor.M_MODE;
            this.m_nR = _backgroundByColor.m_nR;
            this.m_nG = _backgroundByColor.m_nG;
            this.m_nB = _backgroundByColor.m_nB;
        }

        /// <summary>
        /// Gets or sets background color mode
        /// </summary>
        public BACKGROUNDBYCOLOR_MODE MODE
        {
            get { return M_MODE; }
            set { M_MODE = value; }
        }

        /// <summary>
        /// gets or sets R
        /// </summary>
        public int R
        {
            get { return m_nR; }
            set { m_nR = value; }
        }

        /// <summary>
        /// gets or sets G
        /// </summary>
        public int G
        {
            get { return m_nG; }
            set { m_nG = value; }
        }

        /// <summary>
        /// gets or sets b
        /// </summary>
        public int B
        {
            get { return m_nB; }
            set { m_nB = value; }
        }

        /// <summary>
        /// Execute the filter
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            Color color = Color.Transparent;
            
            switch(M_MODE)
            {
                case BACKGROUNDBYCOLOR_MODE.AVERAGE_COLOR:
                    color = ColorFunctions.GetAverageColor(_bitmap);
                    break;

                case BACKGROUNDBYCOLOR_MODE.DOMINANT_COLOR:
                    color = ColorFunctions.GetDominantColor(_bitmap);
                    break;

                case BACKGROUNDBYCOLOR_MODE.MEAN_COLOR:
                    color = ColorFunctions.GetMeanValue(_bitmap);
                    break;

                case BACKGROUNDBYCOLOR_MODE.LUMINANCE_COLOR:
                    Statistics an = new Statistics(_bitmap);
                    an.SortBy(PROCESSING_MODE.Luminance);
                    color = an[0].Color;
                    break;
            }

            UnsafeBitmap bitmap = _bitmap;

            int nHeight = bitmap.Height;
            int nWidth = bitmap.Width;

            Color colorToSet = Color.Transparent;
            Color colorTemp = Color.Transparent;
            Color colorBlack = Definitions.Black;
            Color colorWhite = Definitions.White;

            color = Color.FromArgb(color.R, color.G, color.B);

            int y = 0;
            int x = 0;

            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    colorTemp = bitmap.GetPixel(x, y);
                    if (ColorFunctions.IsInColorTolerance(color, Color.FromArgb(colorTemp.R, color.G, color.B), 10, 10, 10))
                    {
                        colorToSet = colorBlack;
                    }
                    else
                    {
                        colorToSet = colorWhite;
                    }
                    bitmap.SetPixel(x, y, colorToSet);
                }
            }
            return _bitmap;
        }

        /// <summary>
        /// use this to create a deep copy
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new BackgroundByColor(this);
        }
    }
}
